package config

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"nettools/shared/models"
)

// LoadConfig 直接加载配置文件（简化版）
func LoadConfig(configPath string) (*models.ServerConfig, error) {
	// 读取文件内容
	data, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("读取配置文件失败: %w", err)
	}

	// 解析JSON配置
	var config models.ServerConfig
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("解析配置文件失败: %w", err)
	}

	// 设置默认值
	if config.Host == "" {
		config.Host = "0.0.0.0"
	}
	if config.Port == 0 {
		config.Port = 9090
	}
	if config.MaxConnections == 0 {
		config.MaxConnections = 1000
	}
	if config.MaxServicesPerClient == 0 {
		config.MaxServicesPerClient = 10
	}

	return &config, nil
}

// ConfigManager 配置管理器
type ConfigManager struct {
	config   *models.ServerConfig
	filePath string
}

// NewConfigManager 创建配置管理器
func NewConfigManager(configPath string) *ConfigManager {
	return &ConfigManager{
		filePath: configPath,
		config:   models.DefaultServerConfig(),
	}
}

// LoadConfig 加载配置文件
func (cm *ConfigManager) LoadConfig() error {
	if cm.filePath == "" {
		// 如果没有指定配置文件，使用默认配置
		return nil
	}

	// 检查文件是否存在
	if _, err := os.Stat(cm.filePath); os.IsNotExist(err) {
		// 文件不存在，创建默认配置文件
		return cm.SaveConfig()
	}

	// 读取文件内容
	data, err := os.ReadFile(cm.filePath)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %w", err)
	}

	// 验证是否为JSON格式
	ext := filepath.Ext(cm.filePath)
	if ext != ".json" {
		return fmt.Errorf("不支持的配置文件格式: %s，仅支持JSON格式", ext)
	}

	// 解析JSON配置
	err = json.Unmarshal(data, cm.config)
	if err != nil {
		return fmt.Errorf("解析配置文件失败: %w", err)
	}

	return cm.validateConfig()
}

// SaveConfig 保存配置到文件
func (cm *ConfigManager) SaveConfig() error {
	if cm.filePath == "" {
		return fmt.Errorf("未指定配置文件路径")
	}

	// 确保目录存在
	dir := filepath.Dir(cm.filePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建配置目录失败: %w", err)
	}

	// 验证是否为JSON格式
	ext := filepath.Ext(cm.filePath)
	if ext != ".json" {
		return fmt.Errorf("不支持的配置文件格式: %s，仅支持JSON格式", ext)
	}

	// 序列化为JSON格式
	data, err := json.MarshalIndent(cm.config, "", "  ")
	if err != nil {
		return fmt.Errorf("序列化配置失败: %w", err)
	}

	// 写入文件
	err = os.WriteFile(cm.filePath, data, 0644)
	if err != nil {
		return fmt.Errorf("写入配置文件失败: %w", err)
	}

	return nil
}

// GetConfig 获取配置
func (cm *ConfigManager) GetConfig() *models.ServerConfig {
	return cm.config
}

// SetConfig 设置配置
func (cm *ConfigManager) SetConfig(config *models.ServerConfig) error {
	cm.config = config
	return cm.validateConfig()
}

// validateConfig 验证配置
func (cm *ConfigManager) validateConfig() error {
	if cm.config == nil {
		return fmt.Errorf("配置不能为空")
	}

	// 验证主机地址
	if cm.config.Host == "" {
		cm.config.Host = "0.0.0.0"
	}

	// 验证服务配置
	if len(cm.config.Services) == 0 {
		return fmt.Errorf("至少需要配置一个服务")
	}

	// 检查端口冲突和有效性
	portMap := make(map[int]string)
	for _, service := range cm.config.Services {
		// 验证端口范围
		if service.Port < 1 || service.Port > 65535 {
			return fmt.Errorf("服务 '%s' 端口号无效: %d", service.Name, service.Port)
		}

		// 检查端口冲突
		if existingService, exists := portMap[service.Port]; exists {
			return fmt.Errorf("端口 %d 冲突: 服务 '%s' 和 '%s'", service.Port, service.Name, existingService)
		}
		portMap[service.Port] = service.Name

		// 验证服务名称
		if service.Name == "" {
			return fmt.Errorf("服务名称不能为空")
		}

		// 验证服务类型
		if service.ServiceType != "proxy" && service.ServiceType != "management" {
			return fmt.Errorf("服务 '%s' 类型无效: %s (只支持 'proxy' 或 'management')", service.Name, service.ServiceType)
		}

		// 注意：现在使用全局认证配置，不再需要验证服务级别认证配置
	}

	// 验证全局认证配置
	if cm.config.Security.DefaultAuthType == "" {
		cm.config.Security.DefaultAuthType = "token"
	}

	switch cm.config.Security.DefaultAuthType {
	case "token", "key", "cert":
		// 支持的认证类型
	default:
		return fmt.Errorf("默认认证类型无效: %s", cm.config.Security.DefaultAuthType)
	}

	// 验证TLS配置
	if cm.config.Security.TLSEnabled {
		if cm.config.Security.TLSCertFile == "" {
			return fmt.Errorf("启用TLS时必须指定证书文件")
		}
		if cm.config.Security.TLSKeyFile == "" {
			return fmt.Errorf("启用TLS时必须指定密钥文件")
		}
	}

	// 验证性能配置
	if cm.config.Performance.MaxConnections <= 0 {
		cm.config.Performance.MaxConnections = 1000
	}

	if cm.config.Performance.MaxServicesPerClient <= 0 {
		cm.config.Performance.MaxServicesPerClient = 10
	}

	if cm.config.Performance.BufferSize <= 0 {
		cm.config.Performance.BufferSize = 32 * 1024 // 32KB
	}

	// 验证日志配置
	if cm.config.Logging.Level == "" {
		cm.config.Logging.Level = "info"
	}

	return nil
}

// GetServices 获取所有服务配置
func (cm *ConfigManager) GetServices() []models.ServerService {
	return cm.config.Services
}

// GetServiceByName 根据名称获取服务配置
func (cm *ConfigManager) GetServiceByName(name string) (*models.ServerService, bool) {
	for _, service := range cm.config.Services {
		if service.Name == name {
			return &service, true
		}
	}
	return nil, false
}

// GetServiceByPort 根据端口获取服务配置
func (cm *ConfigManager) GetServiceByPort(port int) (*models.ServerService, bool) {
	for _, service := range cm.config.Services {
		if service.Port == port {
			return &service, true
		}
	}
	return nil, false
}

// GetEnabledServices 获取启用的服务配置
func (cm *ConfigManager) GetEnabledServices() []models.ServerService {
	var enabledServices []models.ServerService
	for _, service := range cm.config.Services {
		if service.Enabled {
			enabledServices = append(enabledServices, service)
		}
	}
	return enabledServices
}

// GetProxyServices 获取代理服务配置
func (cm *ConfigManager) GetProxyServices() []models.ServerService {
	var proxyServices []models.ServerService
	for _, service := range cm.config.Services {
		if service.Enabled && service.ServiceType == "proxy" {
			proxyServices = append(proxyServices, service)
		}
	}
	return proxyServices
}

// GetManagementServices 获取管理服务配置
func (cm *ConfigManager) GetManagementServices() []models.ServerService {
	var mgmtServices []models.ServerService
	for _, service := range cm.config.Services {
		if service.Enabled && service.ServiceType == "management" {
			mgmtServices = append(mgmtServices, service)
		}
	}
	return mgmtServices
}

// GetListenAddr 获取指定服务的监听地址
func (cm *ConfigManager) GetListenAddr(serviceName string) (string, error) {
	service, exists := cm.GetServiceByName(serviceName)
	if !exists {
		return "", fmt.Errorf("服务 '%s' 不存在", serviceName)
	}
	return fmt.Sprintf("%s:%d", cm.config.Host, service.Port), nil
}

// IsAuthEnabled 检查全局认证是否启用
func (cm *ConfigManager) IsAuthEnabled() bool {
	return cm.config.Security.DefaultAuthEnabled
}

// IsServiceAuthRequired 检查指定服务是否需要认证
// 注意：现在使用全局认证配置，所有服务共享相同的认证设置
func (cm *ConfigManager) IsServiceAuthRequired(serviceName string) bool {
	// 所有服务都使用全局认证设置
	return cm.config.Security.DefaultAuthEnabled
}

// IsTLSEnabled 是否启用TLS
func (cm *ConfigManager) IsTLSEnabled() bool {
	return cm.config.Security.TLSEnabled
}

// IsPSKEnabled 是否启用PSK加密
func (cm *ConfigManager) IsPSKEnabled() bool {
	return cm.config.Security.PSKEnabled
}

// GetAuthType 获取指定服务的认证类型
// 注意：现在使用全局认证配置，所有服务共享相同的认证类型
func (cm *ConfigManager) GetAuthType(serviceName string) string {
	// 所有服务都使用全局认证类型
	return cm.config.Security.DefaultAuthType
}

// GetAuthConfig 获取指定服务的认证配置
// 注意：现在使用全局认证配置，所有服务共享相同的认证配置
func (cm *ConfigManager) GetAuthConfig(serviceName string) map[string]string {
	// 返回全局认证配置
	if cm.config.Security.GlobalAuthConfig == nil {
		return make(map[string]string)
	}
	return cm.config.Security.GlobalAuthConfig
}
